﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Xml.Serialization;
using System.Threading;
using System.Web;
using System.Net.Cache;
using CommonTools;
using ANYCHATAPI;

namespace BusinessCloud
{
    public partial class MainForm : Form
    {
        //所有登录的用户<UserId,UserName>
        public static Dictionary<int, string> OnlineUsers = new Dictionary<int, string>();
        //所有在房间的用户<UserId,RoomId>
        public static Dictionary<int, int> InRoomUsers = new Dictionary<int, int>();

        //被邀请等待处理的用户，<邀请人id,被邀请人信息>
        Dictionary<int, UserInfo> InviteList = new Dictionary<int, UserInfo>();
        //记录所有被邀请人，与上面的InvateList配合使用，加快速度。
        List<int> InviteGuestList = new List<int>();

        /// <summary>
        /// 判断用户是否已登录
        /// </summary>
        /// <param name="id">用户ID</param>
        /// <returns></returns>
        public static bool isUserExist(int id)
        {
            return OnlineUsers.ContainsKey(id);
        }

        /// <summary>
        /// 判断用户是否在指定房间里
        /// </summary>
        /// <param name="UserId">用户ID</param>
        /// <param name="RoomId">房间号</param>
        /// <returns>
        /// 1 --- 在房间
        /// 0 --- 不在房间
        /// -1 -- 在不同房间
        /// </returns>
        public static int isUserInRoom(int UserId, int RoomId)
        {
            int rtn = 0;

            if (InRoomUsers.ContainsKey(UserId)) //被邀请用户在房间
            {
                if (RoomId == InRoomUsers[UserId]) //在相同房间
                {
                    rtn = 1;
                }
                else
                    rtn = -1;
            }

            return rtn;
        }

        /// <summary>
        /// 根据用户名称查找用户id
        /// </summary>
        /// <param name="name">用户名称</param>
        /// <returns>return >0找到的id,return=0没找到</returns>
        public static int GetIdByName(string name)
        {
            if (OnlineUsers.ContainsValue(name))
            {
                foreach (KeyValuePair<int, string> kvp in OnlineUsers)
                {
                    if (kvp.Value.Equals(name))
                    {
                        return kvp.Key;
                    }
                }
            }

            return 0;
        }

        /// <summary>
        /// 根据用户id查找用户名称
        /// </summary>
        /// <param name="id">用户id</param>
        /// <returns>找到返回名称,没找到返回""</returns>
        public static string GetNameById(int id)
        {
            if (OnlineUsers.ContainsKey(id))
            {
                return OnlineUsers[id];
            }
            else
                return "";
        }

        //在线用户数量
        public static int OnlineCount()
        {
            return OnlineUsers.Count;
        }

        //在房间用户数量
        public static int InRoomCount()
        {
            return InRoomUsers.Count;
        }


        /// <summary>
        /// 加入邀请队列（一个主人同时只能邀请一个客人，后面的会覆盖前面的）
        /// </summary>
        /// <param name="UserId">邀请人</param>
        /// <param name="GuestId">被邀请人</param>
        /// <param name="GuestName"></param>
        /// <param name="GuestRoomId"></param>
        void AddInviteList(int UserId, int GuestId, string GuestName, int GuestRoomId)
        {
            UserInfo u = new UserInfo();
            u.GuestId = GuestId;
            u.GuestName = GuestName;
            u.GuestRoomId = GuestRoomId;
            if (InviteList.ContainsKey(UserId))
                InviteList[UserId] = u;
            else
                InviteList.Add(UserId, u);

            //更新快查列表
            if (!InviteGuestList.Contains(GuestId))
                InviteGuestList.Add(GuestId);
        }

        /// <summary>
        /// 移出邀请队列（一个客人同时能被多个主人邀请）
        /// 同时通知邀请人
        /// 每次有用户进入房间时调用
        /// </summary>
        /// <param name="GuestId">被邀请人</param>
        void NoticeAndRemoveInvite(int GuestId, int RoomId)
        {
            //更新快查列表
            InviteGuestList.Remove(GuestId);

            List<int> list = new List<int>();
            //同时通知邀请人
            foreach (KeyValuePair<int, UserInfo> kv in InviteList)
            {
                if (kv.Value.GuestId == GuestId)
                {
                    if (kv.Value.GuestRoomId == RoomId)
                    {
                        log("通知用户 " + kv.Key + ", " + kv.Value.GuestName + " 已进入房间");
                        //发送通知信息
                        string cmd = "*[;1001;" + kv.Value.GuestName + ";" + GuestId + ";" + RoomId + ";]";
                        SendMsgToUser(kv.Key, cmd);
                    }
                    else
                        log("用户 " + kv.Value.GuestName + " 进入房间，但是房间号不同 " + kv.Value.GuestRoomId + " --- " + RoomId);

                    list.Add(kv.Key);
                    return;
                }
            }

            //删除邀请列表中的对应人
            foreach (int k in list)
                InviteList.Remove(k);
        }

        /// <summary>
        /// 查看某用户是否被人邀请过
        /// </summary>
        /// <param name="GuestId"></param>
        /// <returns></returns>
        bool IsInvite(int GuestId)
        {
            return InviteGuestList.Contains(GuestId);
        }

        /// <summary>
        /// 分类处理接收到的消息
        /// </summary>
        /// <param name="UserId">消息来源</param>
        /// <param name="msg">消息内容</param>
        private void ProcessMessage(int UserId, string msg)
        {
            log("ProcessMessage：UserId=" + UserId + ",msg={" + msg + "}");
            if (!msg.StartsWith("*[;"))
                return;

            String[] sl = msg.Split(new Char[] { ';' });
            if (sl.Length < 4)
            {
                log("命令长度不足：[" + sl.Length + "]");
                return;
            }
            //sl[3]固定保存相关用户名
            string GuestName = sl[3];
            int GuestId = 0;
            int rtn;

            //获取用户ID，同时判断是否在线
            GuestId = GetIdByName(GuestName);
            if (GuestId == 0)
            {
                //用户未上线
                log("用户[" + GuestName + "]未上线");
            }
            log("GuestName:" + GuestName + ",GuestId:" + GuestId);
            if (sl[1] == "1000") //邀请用户进入房间
            {
                log(sl[1] + "邀请用户进入房间");
                if (sl.Length < 6)
                {
                    log("命令长度不足：[" + sl.Length + "]");
                    return;
                }

                int RoomId = cs_common.String2Int(sl[4]);

                if (GuestId == 0)
                {
                    //用户未上线
                    string cmd = "*[;1001;" + sl[2] + ";ERROR;;" + GuestName + ";0;" + RoomId + ";]";
                    SendMsgToUser(UserId, cmd);
                    return;
                }

                //被邀请用户是否在房间
                // rtn = isUserInRoom(GuestId, RoomId);
                bool brtn = isUserExist(GuestId);
                if (brtn) //被邀请用户已经在房间
                {
                    log("被邀请用户已经在房间");
                    string cmd = "*[;1000;" + sl[2] + ";" + GetNameById(GuestId) + ";" + RoomId + ";" + sl[4] + ";" + UserId + ";]";
                    SendMsgToUser(GuestId, cmd);

                    cmd = "*[;1001;" + sl[2] + ";OK;;" + GuestName + ";" + GuestId + ";" + RoomId + ";]";
                    SendMsgToUser(UserId, cmd);
                }
                else //被邀请用户不在房间或在不同房间，通知他进入房间
                {
                    log("被邀请用户不在房间，通知他进入房间");
                    //加入邀请队列
                    //AddInviteList(UserId, GuestId, GuestName, RoomId);

                    //string cmd = "*[;1000;" + sl[2] + ";" + GetNameById(GuestId) + ";" + RoomId + ";" + sl[4] + ";" + UserId + ";]";
                    //SendMsgToUser(GuestId, cmd);
                    string cmd = "*[;1001;" + sl[2] + ";ERROR;offline;" + GuestName + ";" + GuestId + ";" + RoomId + ";]";
                    SendMsgToUser(UserId, cmd);

                }
            }
            else if (sl[1] == "2000") //发送文本消息
            {
                log(sl[1] + "发送文本消息");
                if (sl.Length < 6)
                {
                    log("命令长度不足：[" + sl.Length + "]");
                    return;
                }

                if (GuestId == 0)
                {
                    //用户未上线
                    string cmd = "*[;2001;" + sl[2] + ";ERROR;;" + GuestName + ";" + sl[4] + ";]";
                    SendMsgToUser(UserId, cmd);
                }
                else //把消息转发给目标用户
                {
                    string cmd = "*[;2000;" + sl[2] + ";" + GetNameById(UserId) + ";" + sl[3] + ";" + sl[4] + ";]";
                    SendMsgToUser(GuestId, cmd);
                }
            }
            else if (sl[1] == "2100") //请求远程设备视频，通过UDP把这条命令转发给设备管理服务器
            {
                log(sl[1] + "请求远程设备视频" + sl[4]);
                /*
                string iport = GetServerIP(sl[4]);
                log(iport);
                String[] ss = iport.Split(new Char[] { ':' });
                if (ss.Length < 2)
                {
                    log("查询到的IP:PORT格式不正确");
                    return;
                }

                udp.SendMsg(msg, ss[0]);
                */
            }
            else if (sl[1] == "5000") //根据用户名查询用户ID
            {
                log(sl[1] + "根据用户名查询用户ID");
                if (sl.Length < 6)
                {
                    log("命令长度不足：[" + sl.Length + "]");
                    return;
                }

                string cmd = "*[;5001;" + sl[2] + ";" + GuestName + ";" + GuestId + ";" + sl[4] + ";]";
                SendMsgToUser(UserId, cmd);
            }
            else if (sl[1] == "9000") //视频呼叫请求
            {
                log(sl[1] + "视频呼叫");
                int CallCenterVideoServerId = GetIdByName("CallCenterVideoServer");
                if (CallCenterVideoServerId == 0)
                {
                    //用户未上线
                    string cmd = "*[;9001;" + sl[2] + ";" + "ERROR;CallCenterVideoServer offline;]";
                    SendMsgToUser(UserId, cmd);
                }
                else //把消息转发给目标用户
                {
                    SendMsgToUser(CallCenterVideoServerId, msg);
                    //回应视频终端
                    string cmd = "*[;9001;" + sl[2] + ";OK;" + DateTime.Now.ToString("yyyyMMddHHmmss") + ";]";
                    SendMsgToUser(UserId, cmd);
                }
            }
            else if (sl[1] == "9100") //救援结束
            {
                log(sl[1] + "救援结束");
                int DeviceId = GetIdByName(GuestName);
                if (DeviceId == 0)
                {
                    //用户未上线
                    string cmd = "*[;9101;" + sl[2] + ";ERROR;" + GuestName + " no found;]";
                    SendMsgToUser(UserId, cmd);
                }
                else //把消息转发给目标用户
                {
                    //回应用户OK
                    string cmd = "*[;9101;" + sl[2] + ";OK;" + GuestName + ";]";
                    SendMsgToUser(UserId, cmd);
                    //把消息转发给目标用户
                    SendMsgToUser(DeviceId, msg);
                }
            }

        }

        /// <summary>
        /// 通过透明传输通道，发送消息给另外一个用户
        /// </summary>
        /// <param name="id">接收消息的用户id，0表示发消息给服务器</param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public bool SendMsgToUser(int id, string msg)
        {
            int uid = id;
            if (id == 1)
            {
                uid = GetIdByName("CallCenterVideoServer");
            }
            string sUrl = MakeUrl("transbuffer");
            string buf = cs_common.EncodeBase64(msg);
            string sData = "{\"userid\" : " + uid + ",\"databuf\" : \"" + buf + "\"}";
            return PostData(sUrl, sData);

            /*
            byte[] buf = cs_common.StringToBytes(msg);
            int rtn = AnyChatServerSDK.BRAS_TransBuffer(id, buf, buf.Length);
            if (rtn == 0)
            {
                log("SendMsg to：" + id + " 内容：" + msg + " success");
            }
            else
            {
                log("SendMsg to：" + id + " 内容：" + msg + " error(" + rtn + ")");
            }
            return true;
            */
        }

    }
}
